<?php
function rate_spendnum($filezise, $conn)
{
    global $website_array;
    $file_size_gb = $filezise / (1024 * 1024 * 1024);
    $file_size_mb = $filezise / (1024 * 1024);
    if (!empty($_COOKIE)) {
        if ((empty($_COOKIE['user_key']) || $_COOKIE['user_key'] == '' || $_COOKIE['user_key'] == 'invalid' || $_COOKIE['user_key'] == 'expired')) {
            if ($file_size_mb > (int)$website_array['notlogined']) {
                return [false,-1];
            } else {
                return [true,-1];
            }
        } else {
            $filer = $_COOKIE['user_key'];
            $sql = "SELECT rated,rate,vip FROM user WHERE id = ?";
            $stmt = $conn->prepare($sql);
            $stmt->bind_param("s", $filer);
            if ($stmt->execute()) {
                $result = $stmt->get_result()->fetch_assoc();
                $rated = $result['rated'];
                $rate = $result['rate'];
                $vip = $result['vip'];
                $currentDateTime = new DateTime(); 
                $vipnowtime = new DateTime($vip);
                $hasused = $rated + $file_size_gb;
                if ($hasused > $rate) {
                    if($vipnowtime < $currentDateTime){ 
                        return [false,-1];
                    }
                }
                $sql = "UPDATE user SET rated = rated + ? WHERE id = ?";
                $stmt = $conn->prepare($sql);
                $stmt->bind_param("ds", $file_size_gb, $filer);
                if ($stmt->execute()) {
                    if($vipnowtime > $currentDateTime){
                        return [true,0];
                    }else{
                        return [true,-1];
                    }
                } else {
                    return [false,-1];
                }
            } else {
                return [false,-1];
            }
        }
    } else {
        if ($file_size_mb > 5) {
            return [false,-1];
        } else {
            return [true,-1];
        }
    }
}
function duetosizegetspeed($file_sizes,$is_vip = false)
{
    global $speed_download_arr;
    if ($is_vip) {
        return $file_sizes; 
    }
    $download_speeds = 0;
    if ($file_sizes < 1024 * 1024) {
        $download_speeds = $speed_download_arr['a']; 
    } elseif ($file_sizes < 1024 * 1024 * 5) {
        $download_speeds = $speed_download_arr['b'];
    } elseif ($file_sizes < 1024 * 1024 * 10) {
        $download_speeds = $speed_download_arr['c'];
    } elseif ($file_sizes < 1024 * 1024 * 50) {
        $download_speeds = $speed_download_arr['d'];
    } elseif ($file_sizes < 1024 * 1024 * 100) {
        $download_speeds = $speed_download_arr['e'];
    } elseif ($file_sizes < 1024 * 1024 * 500) {
        $download_speeds = $speed_download_arr['f'];
    } else {
        $download_speeds = $speed_download_arr['g'];
    }
    return $download_speeds;
}
function getRemoteFileSize($url)
{
    $headers = @get_headers($url);
    if ($headers && strpos($headers[0], '200')) {
        foreach ($headers as $header) {
            if (strpos($header, 'Content-Length') !== false) {
                return intval(substr($header, strlen('Content-Length: ')));
            }
        }
    }
    return false;
}
$file_identifier = $_SERVER['QUERY_STRING'] ?? null;
if ($file_identifier === null) {
    echo json_encode(['error' => 'File not found.', 'status' => 0]);
    exit;
}
$pwd_get = null;
require($_SERVER['DOCUMENT_ROOT'].'/cofd/functions.php');
if (strpos($file_identifier, "&pwd=") !== false) {
    $pwd_get = explode("&pwd=", $file_identifier)[1];
    $file_identifier = encrypt(explode("&pwd=", $file_identifier)[0],'D','yhsdylpo9342');
}
require($_SERVER['DOCUMENT_ROOT'] . '/cofd/common.php');
require $_SERVER['DOCUMENT_ROOT'] . '/vendor/autoload.php';
require($_SERVER['DOCUMENT_ROOT'] . '/setting.php');
require($_SERVER['DOCUMENT_ROOT'].'/setting.php');
use Aws\S3\S3Client;
use Aws\Exception\AwsException;

function generate_urlsigndownload($bucket, $objectKey, $accessKeyId, $secretAccessKey)
{
    $region = 'rainyun';
    $s3Client = new S3Client([
        'version' => 'latest',
        'region' => $region,
        'endpoint' => 'https://cn-sy1.rains3.com',
        'credentials' => [
            'key' => $accessKeyId,
            'secret' => $secretAccessKey
        ],
        'use_path_style_endpoint' => true,
        'suppress_php_deprecation_warning' => true
    ]);

    $command = $s3Client->getCommand('GetObject', [
        'Bucket' => $bucket,
        'Key' => $objectKey
    ]);

    try {
        $presignedUrl = (string) $s3Client->createPresignedRequest($command, '+1 hour')->getUri();
        return $presignedUrl;
    } catch (AwsException $e) {
        return "Error: " . $e->getMessage();
    }
}
function delete_urlsigndownload($bucket, $objectKey, $accessKeyId, $secretAccessKey)
{
    $region = 'rainyun';
    $s3Client = new S3Client([
        'version' => 'latest',
        'region' => $region,
        'endpoint' => 'https://cn-sy1.rains3.com',
        'credentials' => [
            'key' => $accessKeyId,
            'secret' => $secretAccessKey
        ],
        'http' => [
            'verify' => false,
        ],
        'use_path_style_endpoint' => true,
        'suppress_php_deprecation_warning' => true
    ]);

    try {
        $s3Client->deleteObject([
            'Bucket' => $bucket,
            'Key' => $objectKey
        ]);
    } catch (AwsException $e) {
        echo json_encode(['error' => 'Error: ' . $e->getMessage(), 'status' => 0]);
    }
}
$file_real_downname = null;
$sql = "SELECT `asets`, `pwd`, `numd`, `froms`,`names` FROM files WHERE id = ?";
$stmt = $conn->prepare($sql);
$stmt->bind_param("s", $file_identifier);
$stmt->execute();
$temppath_isossfile = true;
$result = $stmt->get_result();
if ($result->num_rows > 0) {
    $row = $result->fetch_assoc();
    $real_path = null;
    $file_real_downname = $row['names'];
    $temp_path = tempnam(sys_get_temp_dir(), "file_");
    if (substr($row['asets'], 0, 5) == 's3::>') {
        $splitted = explode('s3::>', $row['asets'])[1];
        $real_path = generate_urlsigndownload($rainyun_oss['bucket'], $splitted, $rainyun_oss['access_key_id'], $rainyun_oss['access_key_secret']);
        $temp_path = $real_path;
        $temppath_isossfile = false;
    } else {
        $real_path = $_SERVER['DOCUMENT_ROOT'] . '/uploads/' . $row['asets'];
        if (!file_exists($real_path)) {
            echo json_encode(['error' => 'File not found.', 'status' => 0]);
            $stmt->close();
            $conn->close();
            exit;
        }
        if (!copy($real_path, $temp_path)) {
            echo json_encode(['error' => 'File not found.', 'status' => 0]);
            $stmt->close();
            $conn->close();
            exit;
        }
    }
    $pwds = $row['pwd'];
    if (($pwds != null || $pwds != "") && $pwds != "null") {
        if ($pwds != $pwd_get) {
            echo json_encode(['error' => 'PASSWORD ERROR', 'status' => 0]);
            $stmt->close();
            $conn->close();
            exit;
        }
    }
    if ($row['froms'] == 'visitor') {
        if ($row['numd'] == 0) {
            echo json_encode(['error' => 'The number of downloads has been reached', 'status' => 0]);
            if ($temppath_isossfile) {
                unlink($real_path);
                unlink($temp_path);
            } else {
                delete_urlsigndownload($rainyun_oss['bucket'], $row['names'], $rainyun_oss['access_key_id'], $rainyun_oss['access_key_secret']);
            }
            $sql = "delete from files where id = ?";
            $stmt = $conn->prepare($sql);
            $stmt->bind_param("s", $file_identifier);
            $stmt->execute();
            $stmt->close();
            $conn->close();
            exit;
        } else {
            $sql = "update files set numd=numd-1 where id = ?";
            $stmt = $conn->prepare($sql);
            $stmt->bind_param("s", $file_identifier);
            $stmt->execute();
        }
    }
    $file_size = null;
    $download_speed = 0;
    if ($row['froms'] == 'visitor') {
        $download_speed = 25600;
    }
    if ($temppath_isossfile === false) {
        $ch = curl_init($temp_path);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HEADER, 0);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        $headers = @get_headers($temp_path, 1);
        if (!isset($headers['Content-Length'])) {
            echo json_encode(['error' => 'Cannot determine file size', 'status' => 0]);
            curl_close($ch);
            exit;
        }
        $file_size = intval($headers['Content-Length']);
        $result_before_speednum = rate_spendnum($file_size, $conn);
        if (!$result_before_speednum[0]) {
            echo json_encode(['error' => 'Download speed limit exceeded', 'status' => 0]);
            $stmt->close();
            $conn->close();
            exit;
        }
        if($result_before_speednum[1] == 0){
            $download_speed_isvip = true;
        }else{
            $download_speed_isvip = false;
        }
        $download_speed = duetosizegetspeed($file_size, $download_speed_isvip);
        $bytes_sent = 0;
        $start_time = microtime(true);
        header('Content-Description: File Transfer');
        header('Content-Type: application/octet-stream');
        header('Content-Disposition: attachment; filename="' . $file_real_downname . '"');
        header('Expires: 0');
        header('Cache-Control: must-revalidate');
        header('Pragma: public');
        if ($file_size > 0) {
            header('Content-Length: ' . $file_size);
        }
        ob_clean();
        flush();
        $fh = fopen('php://temp', 'w+');
        if ($fh === false) {
            echo json_encode(['error' => 'Cannot open file for reading', 'status' => 0]);
            curl_close($ch);
            exit;
        }
        while (!feof($fh)) {
            $chunk = curl_exec($ch);
            if (curl_errno($ch)) {
                echo json_encode(['error' => 'Cannot open file for reading', 'status' => 0]);
                fclose($fh);
                curl_close($ch);
                exit;
            }
            if ($chunk === false || empty($chunk)) {
                break;
            }
            fwrite($fh, $chunk);
            fflush($fh);
            rewind($fh);
            while (!feof($fh)) {
                $buffer = fread($fh, $download_speed);
                echo $buffer;
                ob_flush();
                flush();
                $bytes_sent += strlen($buffer);
                $elapsed_time = microtime(true) - $start_time;
                $expected_time = $bytes_sent / $download_speed;
                if ($elapsed_time < $expected_time) {
                    usleep(($expected_time - $elapsed_time) * 1e6);
                }
            }
            fseek($fh, 0, SEEK_END);
        }
        fclose($fh);
        curl_close($ch);
        if ($file_size > 0 && $bytes_sent != $file_size) {
            echo json_encode(['error' => 'Download incomplete', 'status' => 0]);
            exit;
        }
        exit;
    } else {
        $file_size = filesize($temp_path);
        $result_before_speednum = rate_spendnum($file_size, $conn);
        if (!$result_before_speednum[0]) {
            echo json_encode(['error' => 'Download speed limit exceeded', 'status' => 0]);
            $stmt->close();
            $conn->close();
            exit;
        }
        if($result_before_speednum[1] == 0){
            $download_speed_isvip = true;
        }else{
            $download_speed_isvip = false;
        }
        $download_speed = duetosizegetspeed($file_size, $download_speed_isvip);
        $handle = fopen($temp_path, 'rb');
        if ($handle === false) {
            echo json_encode(['error' => 'Cannot open file for reading', 'status' => 0]);
            unlink($temp_path);
            $stmt->close();
            $conn->close();
            exit;
        }
    }
    header('Content-Description: File Transfer');
    header('Content-Type: application/octet-stream');
    header('Content-Disposition: attachment; filename="' . $file_real_downname . '"');
    header('Expires: 0');
    header('Cache-Control: must-revalidate');
    header('Pragma: public');
    header('Content-Length: ' . $file_size);
    ob_clean();
    flush();
    $start_time = microtime(true);
    while (!feof($handle)) {
        $buffer = fread($handle, $download_speed);
        echo $buffer;
        ob_flush();
        flush();
        $elapsed_time = microtime(true) - $start_time;
        $expected_time = ftell($handle) / $download_speed;
        if ($elapsed_time < $expected_time) {
            usleep(($expected_time - $elapsed_time) * 1e6);
        }
    }
    fclose($handle);
    if ($temppath_isossfile) {
        unlink($temp_path);
    }
    exit;
} else {
    echo json_encode(['error' => 'File not found.', 'status' => 0]);
    exit;
}

$stmt->close();
$conn->close();
